#include "facekeypointdetector.h"
#include <algorithm>

#include <fstream>
#define fmax(a,b)            (((a) > (b)) ? (a) : (b))
#define fmin(a,b)            (((a) > (b)) ? (b) : (a))


inline void FaceKeypointDetector::Release() {
    if (Net != nullptr)
    {
        delete Net;
        Net = nullptr;
    }
}

bool LoadKeypointInfo(std::vector<float>& KeypointMeanshape)
{
    KeypointMeanshape.clear();

    std::ifstream infile;
    std::string t1;

    infile.open("G:/data/mean_shape.txt");
    if (!infile.is_open())
        return false;
    while (!infile.eof())
    {
        infile >> t1;
        KeypointMeanshape.push_back(stringToNum<float>(t1) * 2);
    }
    infile.close();
    return true;
}

FaceKeypointDetector::FaceKeypointDetector(const std::string& model_param, const std::string& model_bin) :
    _mean_val{ 128.f, 128.f, 128.f },
    Net(new ncnn::Net())
{
    Init(model_param, model_bin);
    LoadKeypointInfo(_keypoint_meanshape);
}

void FaceKeypointDetector::Init(const std::string& model_param, const std::string& model_bin)
{
    int ret = Net->load_param(model_param.c_str());
    ret = Net->load_model(model_bin.c_str());
}
void FaceKeypointDetector::Detect(QImage& image, std::vector<float>& keypoints)
{

    float scale_w = image.width() / 224.f;
    float scale_h = image.height() / 224.f;
    ncnn::Mat in = ncnn::Mat::from_pixels_resize(image.bits(), ncnn::Mat::PIXEL_RGBA2BGR, image.width(), image.height(), 224, 224);
    const float norm_vals[3] = { 1 / 255.f, 1 / 255.f, 1 / 255.f };
    in.substract_mean_normalize(_mean_val, norm_vals);
    ncnn::Extractor ex = Net->create_extractor();
    ex.set_light_mode(true);
    ex.set_num_threads(4);
    ex.input(0, in);
    ncnn::Mat out;
    ex.extract(155, out);
    std::ofstream ofile;
    ofile.open("G:/data/myfile.txt");
    keypoints.resize(out.w);
    for (int j = 0; j < out.w; j++)
    {
        keypoints[j] = out[j] + _keypoint_meanshape[j];
        if (j % 2 == 0)
        {
            keypoints[j] = keypoints[j] * scale_w;
        }
        else
        {
            keypoints[j] = keypoints[j] * scale_h;
        }

        ofile << keypoints[j] << std::endl;
    }
    ofile.close();

    return;
}


FaceKeypointDetector::~FaceKeypointDetector() {
    Release();
}
